/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

int InterpretExpression_DeclareObjects( struct ZlangRuntime *rt , struct ZlangObject *master_obj , struct ZlangInterpretStatementContext *interp_stat_ctx , struct ZlangInterpretExpressionContext *interp_expr_ctx , struct ZlangObject *clone_obj , struct ZlangObject **result_obj )
{
	char					*embellish_name = NULL ;
	char					*embellish2_name = NULL ;
	struct ZlangTokenDataUnitHeader		*token_info1 = NULL ;
	char					*token1 = NULL ;
	struct ZlangTokenDataUnitHeader		*token_info2 = NULL ;
	char					*token2 = NULL ;
	struct ZlangObject			*expr_obj = NULL ;
	struct ZlangObject			*query_obj = NULL ;
	struct ZlangTokenDataUnitHeader		*new_var_name_info = NULL ;
	char					*new_var_name = NULL ;
	struct ZlangObject			*new_var_obj = NULL ;
	struct ZlangInterpretStatementContext	eval_interp_stat_ctx ;
	struct ZlangInterpretStatementContext	refer_interp_stat_ctx ;
	
	int					nret = 0 ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT_ENTER_FUNCTION(rt)
	
	TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "master_obj " ); DebugPrintObject( rt , master_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "clone_obj " ); DebugPrintObject( rt , clone_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "interp_stat_ctx->create_new_object_use_existed_name[%d]" , interp_stat_ctx->create_new_object_use_existed_name )
	
	PEEKTOKEN_AND_SAVEINFO( rt , token_info1 , token1 )
	while( rt->travel_token_info->token_type == TOKEN_TYPE_COMPARE_LT )
	{
		NEXTTOKEN( rt )
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info1 , token1 )
		if( rt->travel_token_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect identification but '%s'" , rt->travel_token )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
		
		embellish_name = token1 ;
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info1 , token1 )
		if( rt->travel_token_info->token_type != TOKEN_TYPE_PART_OF_STATEMENT && rt->travel_token_info->token_type != TOKEN_TYPE_COMPARE_GT )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' or '>' but '%s'" , rt->travel_token )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
		
		if( rt->travel_token_info->token_type == TOKEN_TYPE_COMPARE_GT )
			break;
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info1 , token1 )
		if( rt->travel_token_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect identification but '%s'" , rt->travel_token )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
		
		embellish2_name = token1 ;
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info1 , token1 )
		if( rt->travel_token_info->token_type != TOKEN_TYPE_PART_OF_STATEMENT && rt->travel_token_info->token_type != TOKEN_TYPE_COMPARE_GT )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' or '>' but '%s'" , rt->travel_token )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
		
		break;
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "embellish_name[%s] embellish2_name[%s]" , embellish_name , embellish2_name )
	
	for( ; ; )
	{
		TRAVELTOKEN_AND_SAVEINFO( rt , new_var_name_info , new_var_name )
		if( rt->travel_token_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect identification but '%s'" , rt->travel_token )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
		
		if( master_obj == NULL )
		{
			query_obj = QueryObjectInStatementSegment( rt , new_var_name ) ;
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "QueryObjectInStatementSegment query_obj[%s] return " , new_var_name ); DebugPrintObject( rt , query_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			if( query_obj && interp_stat_ctx->create_new_object_use_existed_name == 0 )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_HAD_DECLARED , "object '%s' had declared" , new_var_name )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_OBJECT_HAD_DECLARED;
			}
		}
		else
		{
			query_obj = QueryPropertyInObjectByPropertyName( rt , master_obj , new_var_name ) ;
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "QueryPropertyInObjectByPropertyName query_obj[%s] return " , new_var_name ); DebugPrintObject( rt , query_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			if( query_obj )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_HAD_DECLARED , "object '%s' had declared in object[%s]" , new_var_name , GetObjectName(master_obj) )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_OBJECT_HAD_DECLARED;
			}
		}
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info2 , token2 )
		if( token_info2->token_type == TOKEN_TYPE_EVAL )
		{
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				PRINT_TABS_AND_FORMAT( rt , "CALL InterpretExpression , last_token[%s][%s]" , _zlang_token_type_str , rt->travel_token )
			}
			memset( & eval_interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			eval_interp_stat_ctx.token_of_expression_end1 = TOKEN_TYPE_PART_OF_STATEMENT ;
			eval_interp_stat_ctx.token_of_expression_end2 = TOKEN_TYPE_END_OF_STATEMENT ;
			expr_obj = NULL ;
			nret = InterpretExpression( rt , & eval_interp_stat_ctx , & expr_obj ) ;
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InterpretExpression return[%d] last_token[%s][%s] " , nret , _zlang_token_type_str , rt->travel_token ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
			if( nret == ZLANG_INFO_END_OF_EXPRESSION )
			{
				if( expr_obj == NULL )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect expression" )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_SYNTAX;
				}
			}
			else
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			token_info2 = rt->travel_token_info ;
			token2 = rt->travel_token ;
			
			if( master_obj == NULL )
			{
				if( query_obj && interp_stat_ctx->create_new_object_use_existed_name == 1 )
				{
					UnreferObject( rt , query_obj );
					
					new_var_obj = query_obj ;
					
					nret = CloneObject( rt , & new_var_obj , GetObjectName(new_var_obj) , clone_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return GET_RUNTIME_ERROR_NO(rt);
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
				else
				{
					new_var_obj = CloneObjectInLocalStack( rt , new_var_name , clone_obj ) ;
					if( new_var_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return GET_RUNTIME_ERROR_NO(rt);
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObjectInLocalStack ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
			}
			else
			{
				new_var_obj = AddPropertyInObject( rt , master_obj , clone_obj , new_var_name ) ;
				if( new_var_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return GET_RUNTIME_ERROR_NO(rt);
				}
				else
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "AddPropertyInObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
			}
			
			if( embellish_name )
				SetObjectEmbellishName( rt , new_var_obj , embellish_name );
			if( embellish2_name )
				SetObjectEmbellishName2( rt , new_var_obj , embellish2_name );
			
			if( GetCloneObjectName(new_var_obj) && GetCloneObjectName(expr_obj) && ! IsObjectPropertiesEntityNull(expr_obj) && ! IsTypeOf( rt , new_var_obj , expr_obj ) )
			{
				nret = TryAscensionType( rt , new_var_obj , & expr_obj ) ;
				if( nret == 0 )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left new_var_obj[%s]->type_name[%s] type not matched with right expr_obj[%s]->type_name[%s] type" , GetObjectName(new_var_obj) , GetCloneObjectName(new_var_obj) , GetObjectName(expr_obj) , GetCloneObjectName(expr_obj) )
					return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
				}
				else if( nret == 2 )
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType new_var_obj[%s] and expr_obj[%s] failed" , GetObjectName(new_var_obj) , GetObjectName(expr_obj) )
					return GET_RUNTIME_ERROR_NO(rt);
				}
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObject " ); DebugPrintObject(rt,expr_obj); printf( " to " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			nret = EvalObject( rt , new_var_obj , expr_obj ) ;
			if( nret < 0 )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "EvalObject failed[%d]" , nret )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			else
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
			
			if( interp_stat_ctx->has_const_decorated == TRUE )
			{
				SetConstantObject( new_var_obj );
			}
			
			if( interp_stat_ctx->has_atomic_decorated == TRUE )
			{
				nret = SetAtomicObject( new_var_obj ) ;
				if( nret )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "set atomic object failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_ALLOC;
				}
			}
			
			{
				SetObjectAccessQualifier( new_var_obj , interp_stat_ctx->has_access_qualifier );
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "new object variable , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			if( result_obj )
				(*result_obj) = new_var_obj ;
			
			if( token_info2->token_type == TOKEN_TYPE_PART_OF_STATEMENT )
			{
			}
			else if( token_info2->token_type == TOKEN_TYPE_END_OF_STATEMENT || token_info2->token_type == TOKEN_TYPE_END_OF_SUB_EXPRESSION )
			{
				break;
			}
			else
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "internal error" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_INTERNAL;
			}
		}
		else if( token_info2->token_type == TOKEN_TYPE_REFER )
		{
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				PRINT_TABS_AND_FORMAT( rt , "CALL InterpretExpression , last_token[%s][%s]" , _zlang_token_type_str , rt->travel_token )
			}
			memset( & refer_interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			refer_interp_stat_ctx.token_of_expression_end1 = TOKEN_TYPE_PART_OF_STATEMENT ;
			refer_interp_stat_ctx.token_of_expression_end2 = TOKEN_TYPE_END_OF_STATEMENT ;
			expr_obj = NULL ;
			nret = InterpretExpression( rt , & refer_interp_stat_ctx , & expr_obj ) ;
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InterpretExpression return[%d] last_token[%s][%s] " , nret , _zlang_token_type_str , rt->travel_token ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
			if( nret == ZLANG_INFO_END_OF_EXPRESSION || nret == ZLANG_INFO_END_OF_STATEMENT )
			{
				if( expr_obj == NULL )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect expression" )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_SYNTAX;
				}
			}
			else
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			token_info2 = rt->travel_token_info ;
			token2 = rt->travel_token ;
			
			if( master_obj == NULL )
			{
				if( query_obj && interp_stat_ctx->create_new_object_use_existed_name == 1 )
				{
					UnreferObject( rt , query_obj );
					
					new_var_obj = query_obj ;
					
					nret = CloneObject( rt , & new_var_obj , GetObjectName(new_var_obj) , clone_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return GET_RUNTIME_ERROR_NO(rt);
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
				else
				{
					new_var_obj = CloneObjectInLocalStack( rt , new_var_name , clone_obj ) ;
					if( new_var_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return nret;
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObjectInLocalStack ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
			}
			else
			{
				new_var_obj = AddPropertyInObject( rt , master_obj , clone_obj , new_var_name ) ;
				if( new_var_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return GET_RUNTIME_ERROR_NO(rt);
				}
				else
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "AddPropertyInObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
			}
			
			if( embellish_name )
				SetObjectEmbellishName( rt , new_var_obj , embellish_name );
			if( embellish2_name )
				SetObjectEmbellishName2( rt , new_var_obj , embellish2_name );
			
			if( GetCloneObjectName(new_var_obj) && GetCloneObjectName(expr_obj) && ! IsObjectPropertiesEntityNull(expr_obj) && ! IsTypeOf( rt , new_var_obj , expr_obj ) )
			{
				nret = TryAscensionType( rt , new_var_obj , & expr_obj ) ;
				if( nret == 0 )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left new_var_obj[%s]->type_name[%s] type not matched with right expr_obj[%s]->type_name[%s] type" , GetObjectName(new_var_obj) , GetCloneObjectName(new_var_obj) , GetObjectName(expr_obj) , GetCloneObjectName(expr_obj) )
					return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
				}
				else if( nret == 2 )
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType new_var_obj[%s] and expr_obj[%s] failed" , GetObjectName(new_var_obj) , GetObjectName(expr_obj) )
					return GET_RUNTIME_ERROR_NO(rt);
				}
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "ReferObjectPropertiesEntity " ); DebugPrintObject(rt,expr_obj); printf( " to " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			nret = ReferObjectPropertiesEntity( rt , new_var_obj , expr_obj ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObjectPropertiesEntity failed[%d]" , nret )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			if( interp_stat_ctx->has_const_decorated == TRUE )
			{
				SetConstantObject( new_var_obj );
			}
			
			if( interp_stat_ctx->has_atomic_decorated == TRUE )
			{
				nret = SetAtomicObject( new_var_obj ) ;
				if( nret )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "set atomic object failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_ALLOC;
				}
			}
			
			SetObjectAccessQualifier( new_var_obj , interp_stat_ctx->has_access_qualifier );
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "new object variable , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			if( result_obj )
				(*result_obj) = new_var_obj ;
			
			if( token_info2->token_type == TOKEN_TYPE_PART_OF_STATEMENT )
			{
			}
			else if( token_info2->token_type == TOKEN_TYPE_END_OF_STATEMENT || token_info2->token_type == TOKEN_TYPE_END_OF_SUB_EXPRESSION )
			{
				break;
			}
			else
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "internal error" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_INTERNAL;
			}
		}
		else if( token_info2->token_type == TOKEN_TYPE_CAST_REFER )
		{
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				PRINT_TABS_AND_FORMAT( rt , "CALL InterpretExpression , last_token[%s][%s]" , _zlang_token_type_str , rt->travel_token )
			}
			memset( & refer_interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			refer_interp_stat_ctx.token_of_expression_end1 = TOKEN_TYPE_PART_OF_STATEMENT ;
			refer_interp_stat_ctx.token_of_expression_end2 = TOKEN_TYPE_END_OF_STATEMENT ;
			expr_obj = NULL ;
			nret = InterpretExpression( rt , & refer_interp_stat_ctx , & expr_obj ) ;
			TEST_RUNTIME_DEBUG( rt )
			{
				TOKENTYPE_TO_STRING( rt->travel_token_info->token_type , _zlang_token_type_str )
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InterpretExpression return[%d] last_token[%s][%s] " , nret , _zlang_token_type_str , rt->travel_token ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
			if( nret == ZLANG_INFO_END_OF_EXPRESSION || nret == ZLANG_INFO_END_OF_STATEMENT )
			{
				if( expr_obj == NULL )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect expression" )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_SYNTAX;
				}
			}
			else
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			token_info2 = rt->travel_token_info ;
			token2 = rt->travel_token ;
			
			if( master_obj == NULL )
			{
				if( query_obj && interp_stat_ctx->create_new_object_use_existed_name == 1 )
				{
					UnreferObject( rt , query_obj );
					
					new_var_obj = query_obj ;
					
					nret = CloneObject( rt , & new_var_obj , GetObjectName(new_var_obj) , clone_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return GET_RUNTIME_ERROR_NO(rt);
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
				else
				{
					new_var_obj = CloneObjectInLocalStack( rt , new_var_name , clone_obj ) ;
					if( new_var_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return nret;
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObjectInLocalStack ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
			}
			else
			{
				new_var_obj = AddPropertyInObject( rt , master_obj , clone_obj , new_var_name ) ;
				if( new_var_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return GET_RUNTIME_ERROR_NO(rt);
				}
				else
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "AddPropertyInObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
			}
			
			if( embellish_name )
				SetObjectEmbellishName( rt , new_var_obj , embellish_name );
			if( embellish2_name )
				SetObjectEmbellishName2( rt , new_var_obj , embellish2_name );
			
			if( GetCloneObjectName(new_var_obj) && GetCloneObjectName(expr_obj) && ! IsObjectPropertiesEntityNull(expr_obj) && ! IsTypeOf( rt , new_var_obj , expr_obj ) )
			{
				nret = TryAscensionType( rt , new_var_obj , & expr_obj ) ;
				if( nret == 0 )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left new_var_obj[%s]->type_name[%s] type not matched with right expr_obj[%s]->type_name[%s] type" , GetObjectName(new_var_obj) , GetCloneObjectName(new_var_obj) , GetObjectName(expr_obj) , GetCloneObjectName(expr_obj) )
					return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
				}
				else if( nret == 2 )
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,expr_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType new_var_obj[%s] and expr_obj[%s] failed" , GetObjectName(new_var_obj) , GetObjectName(expr_obj) )
					return GET_RUNTIME_ERROR_NO(rt);
				}
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "UnreferObject " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			nret = UnreferObject( rt , new_var_obj ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "UnreferObject failed[%d]" , nret )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "ReferObject " ); DebugPrintObject(rt,expr_obj); printf( " to " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			nret = ReferObject( rt , new_var_obj , expr_obj ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObject failed[%d]" , nret )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return nret;
			}
			
			if( interp_stat_ctx->has_const_decorated == TRUE )
			{
				SetConstantObject( new_var_obj );
			}
			
			if( interp_stat_ctx->has_atomic_decorated == TRUE )
			{
				nret = SetAtomicObject( new_var_obj ) ;
				if( nret )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "set atomic object failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_ALLOC;
				}
			}
			
			SetObjectAccessQualifier( new_var_obj , interp_stat_ctx->has_access_qualifier );
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "new object variable , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			if( result_obj )
				(*result_obj) = new_var_obj ;
			
			if( token_info2->token_type == TOKEN_TYPE_PART_OF_STATEMENT )
			{
			}
			else if( token_info2->token_type == TOKEN_TYPE_END_OF_STATEMENT || token_info2->token_type == TOKEN_TYPE_END_OF_SUB_EXPRESSION )
			{
				break;
			}
			else
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "internal error" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_INTERNAL;
			}
		}
		else if( token_info2->token_type == TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION || token_info2->token_type == TOKEN_TYPE_PART_OF_STATEMENT || token_info2->token_type == TOKEN_TYPE_END_OF_STATEMENT )
		{
			if( master_obj == NULL )
			{
				if( query_obj && interp_stat_ctx->create_new_object_use_existed_name == 1 )
				{
					UnreferObject( rt , query_obj );
					
					new_var_obj = query_obj ;
					
					nret = CloneObject( rt , & new_var_obj , GetObjectName(new_var_obj) , clone_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return GET_RUNTIME_ERROR_NO(rt);
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
				else
				{
					new_var_obj = CloneObjectInLocalStack( rt , new_var_name , clone_obj ) ;
					if( new_var_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
						return nret;
					}
					else
					{
						TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "CloneObjectInLocalStack ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
			}
			else
			{
				new_var_obj = AddPropertyInObject( rt , master_obj , clone_obj , new_var_name ) ;
				if( new_var_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return GET_RUNTIME_ERROR_NO(rt);
				}
				else
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "AddPropertyInObject ok , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
			}
			
			if( embellish_name )
				SetObjectEmbellishName( rt , new_var_obj , embellish_name );
			if( embellish2_name )
				SetObjectEmbellishName2( rt , new_var_obj , embellish2_name );
			
			if( interp_stat_ctx->has_const_decorated == TRUE )
			{
				SetConstantObject( new_var_obj );
			}
			
			if( interp_stat_ctx->has_atomic_decorated == TRUE )
			{
				nret = SetAtomicObject( new_var_obj ) ;
				if( nret )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "set atomic object failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_ALLOC;
				}
			}
			
			SetObjectAccessQualifier( new_var_obj , interp_stat_ctx->has_access_qualifier );
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "new object variable , " ); DebugPrintObject(rt,new_var_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			if( token_info2->token_type == TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CALL InterpretExpression_InvokeConstractorFunction ..." )
				nret = InterpretExpression_InvokeConstractorFunction( rt , new_var_obj ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeConstractorFunction failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return nret;
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeConstractorFunction ok" )
				}
				
				TRAVELTOKEN_AND_SAVEINFO( rt , token_info2 , token2 )
				if( token_info2->token_type != TOKEN_TYPE_PART_OF_STATEMENT && token_info2->token_type != TOKEN_TYPE_END_OF_STATEMENT )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "unexpect '%s'" , token2 )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_SYNTAX;
				}
			}
			else
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeDefaultConstractorOrDestractorFunction ..." )
				nret = InterpretExpression_InvokeDefaultConstractorOrDestractorFunction( rt , IS_CONSTRACTOR , new_var_obj ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeDefaultConstractorOrDestractorFunction failed[%d]" , nret )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return nret;
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeDefaultConstractorOrDestractorFunction ok" )
				}
			}
			
			if( result_obj )
				(*result_obj) = new_var_obj ;
			
			if( token_info2->token_type == TOKEN_TYPE_END_OF_STATEMENT )
				break;
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "unexpect '%s'" , token2 )
			TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
			return ZLANG_ERROR_SYNTAX;
		}
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT_LEAVE_FUNCTION(rt)
	
	return ZLANG_INFO_END_OF_EXPRESSION;
}

